package dk.snaveponyklub.servlets;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.jdom.Document;
import org.jdom.ProcessingInstruction;
import org.jdom.input.SAXBuilder;
import org.jdom.output.DOMOutputter;

import dk.snaveponyklub.handler.HandlerFactory;

public class XSLTFilter implements Filter {
    ServletContext context;

    public XSLTFilter() {
        System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
    }

    public void init(FilterConfig c) throws ServletException {
        context = c.getServletContext();
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        HttpServletRequest hreq = (HttpServletRequest) request;
        HttpServletResponse hresp = (HttpServletResponse) response;
        ServletResponse res = new BufferingResponseWrapper(hresp);
        chain.doFilter(request, res);
        try {
            hresp.setContentType("application/xhtml+xml");
            transform(((BufferingResponseWrapper) res).getReader(), response.getOutputStream());
        } catch (Throwable e) {
            context.log("XSLT transformation error", e);
            hresp.sendError(500, "XSLT transformation error");
        }
    }

    @SuppressWarnings("rawtypes")
    public void transform(InputStream in, OutputStream out) {
        try {
            SAXBuilder b = new SAXBuilder();
            Document myDocument = b.build(in);
            List pi = myDocument.getContent(new org.jdom.filter.ContentFilter(org.jdom.filter.ContentFilter.PI));
            String xsl = ((ProcessingInstruction) (pi.get(0))).getPseudoAttributeValue("href");

            URL url = new URL(xsl);
            URLConnection urlConn = url.openConnection(); 
            urlConn.setDoInput(true); 
            urlConn.setUseCaches(false);
            DataInputStream dis = new DataInputStream(urlConn.getInputStream());             

            TransformerFactory tFactory = TransformerFactory.newInstance();

            // Make the input sources for the XML and XSLT documents
            DOMOutputter outputter = new DOMOutputter();
            org.w3c.dom.Document domDocument = outputter.output(myDocument);
            Source xmlSource = new DOMSource(domDocument);
            StreamSource xsltSource = new StreamSource(dis);

            // Make the output result for the finished document using
            // the HTTPResponse OutputStream
            StreamResult xmlResult = new StreamResult(out);

            // Get a XSLT transformer
            Transformer transformer = tFactory.newTransformer(xsltSource);

            // Do the transform
            transformer.transform(xmlSource, xmlResult);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    class BufferingResponseWrapper extends HttpServletResponseWrapper {
        CharArrayWriter buffer;
        PrintWriter writer;

        public BufferingResponseWrapper(HttpServletResponse res) {
            super(res);
            buffer = new CharArrayWriter();
            writer = new PrintWriter(buffer);
        }

        public PrintWriter getWriter() {
            return writer;
        }

        InputStream getReader() {
            return new ByteArrayInputStream(buffer.toString().getBytes());
        }
    }

    public static void main(String[] args) {
        XSLTFilter servlet = new XSLTFilter();
        //InputStream is = new ByteArrayInputStream(HandlerFactory.getInstance().getWeekTimeSlots(1, true).getBytes());
        //InputStream is = new ByteArrayInputStream(HandlerFactory.getInstance().getPersonList(true).getBytes());
        InputStream is = new ByteArrayInputStream(HandlerFactory.getInstance().getPerson(5).getBytes());
        servlet.transform(is, System.out);
    }
}
